#include "RLE.h"


RLE::RLE(int totalBlocks)
{
	_totalBlocks = totalBlocks;
}


RLE::~RLE(void)
{
}

unsigned long RLE::performRLE(int8_t *imageList, util::BitStreamWriter *bsw)
{
	int seriesOf0=0;
	unsigned long bitsWritten = 0;
	for(int i=0; i < _totalBlocks; ++i) {
		for(int j=0; j < 16; ++j) {
			int8_t currentNumber = imageList[(i*16)+j];
			if (currentNumber != 0) {

				if(seriesOf0)       // if any 0 on queue
					bitsWritten += fillLast0Series(bsw, seriesOf0);

				bitsWritten += fillNumber(bsw, currentNumber);

			} else {
				++seriesOf0;
			}
		}
		if(seriesOf0)       // if any 0 on queue
			bitsWritten += fillLast0Series(bsw, seriesOf0);
	}
	return bitsWritten;
}

int8_t *RLE::performZigZag(BlockList& blockList)
{
	int8_t *imageList = new int8_t[_totalBlocks*16];
	int position=0;

	for(int i = 0; i < blockList.size(); ++i){
		Matrix m = blockList[i];
		int8_t *temp = blockList[i].zigzag();

		for(int j=0; j < 16; ++j)
			imageList[position++] = temp[j];

		delete[] temp;
	}

	return imageList;
}

unsigned long RLE::performRawEncoding(int8_t *imageList, util::BitStreamWriter *bsw)
{
	unsigned long bitsWritten = 0;
	for(int i=0; i < _totalBlocks; ++i)
		for(int j=0; j < 16; ++j)
			bitsWritten += fillNumber(bsw, imageList[(i*16)+j]);
	return bitsWritten;
}

unsigned long RLE::fillLast0Series(util::BitStreamWriter *bsw, int &seriesOf0)
{
	unsigned long bitsWritten = 0;
	bsw->put_bit(1);
	++bitsWritten;

	--seriesOf0;

	bitsWritten+=4;
	bsw->put(4, seriesOf0);

	seriesOf0 = 0;

	return bitsWritten;
}

unsigned long RLE::fillNumber(util::BitStreamWriter *bsw, int8_t &currentNumber)
{
	uint32_t numberOfBits = 0;
	unsigned long bitsWritten = 0;

	if(currentNumber < 2 && currentNumber > -3)
	{
		numberOfBits = 1;
	}
	else if(currentNumber < 4 && currentNumber > -5)
	{
		numberOfBits = 2;
	}
	else if(currentNumber < 8 && currentNumber > -9)
	{
		numberOfBits = 3;
	}
	else if(currentNumber < 16 && currentNumber > -17)
	{
		numberOfBits = 4;
	}
	else if(currentNumber < 32 && currentNumber > -33)
	{
		numberOfBits = 5;
	}
	else if(currentNumber < 64 && currentNumber > -65)
	{
		numberOfBits = 6;
	}
	else if(currentNumber < 128 && currentNumber > -129)
	{
		numberOfBits = 7;
	}

	if(numberOfBits > 0){
		bsw->put_bit(0);
		++bitsWritten;
		bsw->put(3, numberOfBits-1);
		bitsWritten+=3;
		if(currentNumber >= 0)
			bsw->put_bit(0);
		else
		{
			bsw->put_bit(1);
			currentNumber = (-1*currentNumber)-1;
		}
		bsw->put(numberOfBits, currentNumber);
		bitsWritten+=numberOfBits;
	}

	return bitsWritten;
}

